package model.code.line;

import event.TextReplacementEvent;
import model.caret.TextCaret;
import model.code.CodeFileChunk;
import model.symbol.Keyword;
import model.symbol.Scope;
import model.symbol.Symbol;
import util.ArrayUtil;

/**
 * This is a {@link Line} intended to represent just a data type.
 * This is used for {@link model.symbol.LocalVariable}s, {@link model.code.GlobalVariable}s, and {@link model.symbol.StructureMember}s.
 * @author Neil Dickson
 */
public class TypeLine extends SingleLine {
	public TypeLine(char[] text, CodeFileChunk parent, int locationType, int locationIndex) {
		super(text, parent, locationType, locationIndex);
		reparse();
	}
	public TextReplacementEvent replace(LineObserver culprit,int startCol, int endCol, char[] newText) {
		TextReplacementEvent event = super.replace(culprit,startCol,endCol,newText);
		reparse();
		return event;
	}

	/**
	 * Reparses the line using the language of its parent, if not null.
	 * @return true if the line was reparsed
	 */
	public boolean reparse() {
		// NOTE: reparse() shouldn't look for renames upon calling replace() above, since then you'd never be able to remove a reference!
		return reparse(false);
	}
	public boolean reparse(boolean lookForRenames) {
		if (parent!=null && parent.getLanguage()!=null && parent.getLanguage().getParser()!=null) {
			if (lookForRenames && references!=null) {
				for (int index=0; index<getNumReferences(); ++index) {
					Object object = references[index];
					if (object!=null && (object instanceof Symbol) && !(object instanceof Keyword)) {
						String tokenText = new String(text,referenceIndices[index],getTokenColumn(index+1)-referenceIndices[index]);
						if (!((Symbol)object).getName().equals(tokenText)) {
							replaceJustText(referenceIndices[index],getTokenColumn(index+1),((Symbol)object).getName().toCharArray());
						}
					}
				}
			}

			int[] renameRefsBefore = (Scope.getBeingRenamed()!=null && references!=null) ? ArrayUtil.allIndicesOf(references,Scope.getBeingRenamed()) : null;
			clearReferences();
			clearErrors();
			parent.getLanguage().getParser().tokenizeLine(this);
			int[] renameRefsAfter = (Scope.getBeingRenamed()!=null && references!=null) ? ArrayUtil.allIndicesOf(references,Scope.getBeingRenamed()) : null;
			if (renameRefsAfter!=null && (renameRefsBefore==null || renameRefsBefore.length<renameRefsAfter.length)) {
				if (renameRefsBefore==null) {
					for (int index : renameRefsAfter) {
						Scope.addRenameReference((Symbol)references[index],new TextCaret(null,this,0,index,0));
					}
				}
				else {
					int beforeIndex = 0;
					for (int index : renameRefsAfter) {
						if (beforeIndex>=renameRefsBefore.length || index!=renameRefsBefore[beforeIndex]) {
							Scope.addRenameReference((Symbol)references[index],new TextCaret(null,this,0,index,0));
						}
						else {
							++beforeIndex;
						}
					}
				}
			}
			return true;
		}
		return false;
	}
}